Mini-Challenge Michelle Rohrer¶
Das Ziel dieser Arbeit ist es, einen Steckbrief über ein Land in Form von Experimenten in Bild- und Signalverarbeitung zusammenzustellen.
Im Sommer habe ich mit meinem kleinen Camper eine Tour durch Nordfrankreich gemacht und dabei besondere Momente fotografiert. Diese möchte ich nun in Zusammenarbeit mit diesem Fach bearbeiten und analysieren.
LE1 - Grundlagen der Signal- und Bildverarbeitung¶
Ich werde mich in Bezug auf die Bildverarbeitung auf die räumliche Auflösung von Pixeln und Helligkeit fokussieren.
Bei der Signalverarbeitung werde ich die Wellenformen und die Phasen erkunden.
Meine Reise hat in Paris begonnen, wo der Himmel in den Farbeon eines spektakulären Sonnenunterganges erstrahlte.
from PIL import Image
import matplotlib.pyplot as plt
# Bild öffnen
image_1 = Image.open('IMG_1450_converted.png')
# Bild anzeigen
plt.imshow(image_1)
plt.axis('off')
plt.show()
Von dort an ging es weiter Richtung Le Mans - hier gibt es neben der Weltbekannten Rennstrecke auch kleine Dinge zu entdecken, wie diese Gruppe Enten bei Nacht.
# Bild laden
image_2 = Image.open('IMG_1455_converted.png')
# Bild anzeigen
plt.imshow(image_2)
plt.axis('off')
plt.show()
Vom Landesinneren geht es jetzt Richtung Küste, der Normandie. Dies ist vermutlich eines der geschichtsträchtigsten Regionen des zweiten Weltkrieges.
# Bild laden
image_3 = Image.open('IMG_1470_converted.png')
# Bild anzeigen
plt.imshow(image_3)
plt.axis('off')
plt.show()
Experiment 1¶
WAS: Die Auflösung meiner Bilder ist zu hoch, was die Dateigröße gross macht und weniger geeignet für die kompakte Speicherung in meinem Reisetagebuch.
WIE: Ich werde mit der Reduzierung der Pixelanzahl experimentieren, um die minimale brauchbare Auflösung zu finden, die kaum zu meinem 4K Bild zu unterscheiden ist. Ich werde verschiedene Komprimierungsstufen testen, um die effizienteste Speichermethode zu finden.
WARUM: Dieses Experiment ist hilfreich, weil die Reduzierung der Dateigröße es mir ermöglicht, mehr Bilder in meinem Reisetagebuch zu speichern, ohne wesentliche Details zu verlieren, was dazu beiträgt, das Tagebuch kompakt zu halten.
Bild 3:
Downsampling. Dabei wird das Bild runterskaliert, um Details zu entfernen. Ich fange mit dem 3. Bild an, da es für mich optisch am wenigsten Details hat und ich somit die Auflösung einfacher verschlechtern kann.
# Downsampling
img_3_down = image_3.resize((image_3.width // 2, image_3.height // 2), Image.BILINEAR)
# Bild anzeigen
plt.imshow(img_3_down)
plt.axis('off')
plt.show()
Ich habe nun die Pixelanzahl halbiert, als nächsten Schritt werde ich die Grösse des einzelnen Pixels ausrechnen.
# Funktion zur Berechnung der Pixelgröße
def berechne_pixelgroesse(bild, physische_flaeche):
breite, hoehe = bild.size
pixelanzahl = breite * hoehe
pixelgroesse = physische_flaeche / pixelanzahl
return pixelgroesse, breite, hoehe, pixelanzahl
# physische Fläche: 1m²
physische_flaeche = 1.0
# Berechnung für image_3
pixelgroesse_image_3, breite_image_3, hoehe_image_3, pixelanzahl_image_3 = berechne_pixelgroesse(image_3, physische_flaeche)
# Berechnung für omg_3_down
pixelgroesse_img_3_down, breite_img_3_down, hoehe_img_3_down, pixelanzahl_img_3_down = berechne_pixelgroesse(img_3_down, physische_flaeche)
# Ergebnisse anzeigen
print(f"Bild: image_3")
print(f"Dimensionen: {breite_image_3}x{hoehe_image_3}")
print(f"Anzahl der Pixel: {pixelanzahl_image_3}")
print(f"Größe jedes Pixels: {pixelgroesse_image_3:.10f} Quadratmeter\n")
print(f"Bild: img_3_down")
print(f"Dimensionen: {breite_img_3_down}x{hoehe_img_3_down}")
print(f"Anzahl der Pixel: {pixelanzahl_img_3_down}")
print(f"Größe jedes Pixels: {pixelgroesse_img_3_down:.10f} Quadratmeter\n")
# Vergleich der beiden Bilder
verhaeltnis = pixelgroesse_image_3 / pixelgroesse_img_3_down
print(f"Das Verhältnis der Pixelgrößen (image_3 / img_3_down) ist: {verhaeltnis:.2f}")
Das Bild sieht optisch im Verlgeich zum originalen Bild nicht schlechter aus. Die Pixelzahl hat sich jedoch trastisch verändert (von 4K auf 2K).
Die Grösse des einzelnen Pixels hat sich bei einer Halbierung der Pixelanzahl um Vier vergrössert. Das ist sehr spannend, ich werde die Pixelanzahl nochmals halbieren um zu schauen, was dann mit der Grösse des einzelnen Pixels passiert.
# Downsampling
img_3_down_ = img_3_down.resize((img_3_down.width // 2, img_3_down.height // 2), Image.BILINEAR)
# Bild anzeigen
plt.imshow(img_3_down_)
plt.axis('off')
plt.show()
# Berechnung für img_3_down
pixelgroesse_image_3, breite_image_3, hoehe_image_3, pixelanzahl_image_3 = berechne_pixelgroesse(img_3_down, physische_flaeche)
# Berechnung für img_3_down_
pixelgroesse_img_3_down, breite_img_3_down, hoehe_img_3_down, pixelanzahl_img_3_down = berechne_pixelgroesse(img_3_down_, physische_flaeche)
# Ergebnisse anzeigen
print(f"Bild: image_3_dwon")
print(f"Dimensionen: {breite_image_3}x{hoehe_image_3}")
print(f"Anzahl der Pixel: {pixelanzahl_image_3}")
print(f"Größe jedes Pixels: {pixelgroesse_image_3:.10f} Quadratmeter\n")
print(f"Bild: img_3_down_")
print(f"Dimensionen: {breite_img_3_down}x{hoehe_img_3_down}")
print(f"Anzahl der Pixel: {pixelanzahl_img_3_down}")
print(f"Größe jedes Pixels: {pixelgroesse_img_3_down:.10f} Quadratmeter\n")
# Vergleich der beiden Bilder
verhaeltnis = pixelgroesse_image_3 / pixelgroesse_img_3_down
print(f"Das Verhältnis der Pixelgrößen (Pixel halbiert / Pixel geviertelt) ist: {verhaeltnis:.2f}")
Das Verhältnis ist wieder 0.25. Das bedeutet, jedes mal wenn ich die Pixelanzahl in einem Bild halbiere, so wird jedes Pixel viermal grösser.
Die Pixelgrösse sagt aus, wie viele Details in einem Bild sind. Wird die Pixelgrösse also vergrössert, so hat man weniger Details und weniger feine Strukturen im Bild, da jedes Pixel einen grösseren Bereich der physischen Fläche abdeckt.
Um meine Ergebnisse noch weiter zu analysieren werde ich mir die Pixelanzahl anhand von Histogrammen genauer untersuchen. Ich werde im Verlauf das Originalbild mit dem 2K Bild vergleichen, da diese sich optisch sehr wenig unterscheiden, den Speicher jedoch stark reduziert.
Das erste Histogram zeigt an, wie oft jeder Grauwert in den Bildern vorkommt.
import numpy as np
# Beide Bilder in Graustufen umwandeln
original_img = image_3.convert('L')
pixelated_img = img_3_down.convert('L')
original_np = np.array(original_img)
pixelated_np = np.array(pixelated_img)
# Histogramme erstellen
plt.figure(figsize=(12, 6))
# Histogramm des Originalbildes
plt.subplot(1, 2, 1)
plt.hist(original_np.ravel(), bins=256, range=(0, 256), color='blue', alpha=0.7)
plt.title('Originalbild')
plt.xlabel('Pixelwert')
plt.ylabel('Häufigkeit')
# Histogramm des pixelierten Bildes
plt.subplot(1, 2, 2)
plt.hist(pixelated_np.ravel(), bins=256, range=(0, 256), color='green', alpha=0.7)
plt.title('pixeliertes Bild')
plt.xlabel('Pixelwert')
plt.ylabel('Häufigkeit')
# Histogramme anzeigen
plt.tight_layout()
plt.show()
# Konvertiere beide Bilder in numpy-Arrays
img_np = np.array(image_3)
pixelated_img_np = np.array(img_3_down)
# Farbkanäle für beide Bilder extrahieren
r_channel_img = img_np[:, :, 0]
g_channel_img = img_np[:, :, 1]
b_channel_img = img_np[:, :, 2]
r_channel_pixelated = pixelated_img_np[:, :, 0]
g_channel_pixelated = pixelated_img_np[:, :, 1]
b_channel_pixelated = pixelated_img_np[:, :, 2]
# Subplot erstellen (2 Zeilen, 3 Spalten)
plt.figure(figsize=(15, 10))
# Histogramme für Rot-Kanal (image_3 oben)
plt.subplot(2, 3, 1)
plt.hist(r_channel_img.ravel(), bins=256, range=(0, 256), color='red', alpha=0.8)
plt.title('Red Channel - Original')
# Histogramme für Grün-Kanal (image_3 oben)
plt.subplot(2, 3, 2)
plt.hist(g_channel_img.ravel(), bins=256, range=(0, 256), color='green', alpha=0.8)
plt.title('Green Channel - Original')
# Histogramme für Blau-Kanal (image_3 oben)
plt.subplot(2, 3, 3)
plt.hist(b_channel_img.ravel(), bins=256, range=(0, 256), color='blue', alpha=0.8)
plt.title('Blue Channel - Original')
# Histogramme für Rot-Kanal (pixelated_img_3 unten)
plt.subplot(2, 3, 4)
plt.hist(r_channel_pixelated.ravel(), bins=256, range=(0, 256), color='red', alpha=0.8)
plt.title('Red Channel - Pixelated')
# Histogramme für Grün-Kanal (pixelated_img_3 unten)
plt.subplot(2, 3, 5)
plt.hist(g_channel_pixelated.ravel(), bins=256, range=(0, 256), color='green', alpha=0.8)
plt.title('Green Channel - Pixelated')
# Histogramme für Blau-Kanal (pixelated_img_3 unten)
plt.subplot(2, 3, 6)
plt.hist(b_channel_pixelated.ravel(), bins=256, range=(0, 256), color='blue', alpha=0.8)
plt.title('Blue Channel - Pixelated')
# Layout anpassen und anzeigen
plt.tight_layout()
plt.show()
# wurde mit ChatGPT generiert
Trotz der Halbierung der Pixelanzahl und der dadurch resultierenden Vervierfachung der Pixelgröße zeigt das Bild visuell kaum Unterschiede im Vergleich zur höheren Auflösung. Auch im Histogramm lassen sich nur geringe Abweichungen feststellen.
Dies bestätigt meine anfängliche Vermutung, dass das Bild keine feinen Details enthält, die durch die niedrigere Auflösung verloren gehen würden. Bei Bildern mit weniger feinen Strukturen und weniger hohen Detailanforderungen ist eine solche Verringerung der Pixelanzahl oft visuell schwer wahrnehmbar, besonders bei typischen Betrachtungsabständen oder kleineren Bildgrößen.
Bild 2:
Räumliche Unterabtastung. Dabei wird das Bild in Blöcke unterteilt und der Durchschnittswert der Pixel in jedem Block wird genommen. Ich werde das gleiche Experiment nun bei dem Bild 1 anwenden, da dies optisch mehr Details enthält. Damit müsste die Vergrösserung des Pixels optisch grössere Unterschiede machen. Ich wende jedoch eine andere Technik an, um die Auflösung zu verringern.
# Bild in Blöcke unterteilen
def pixelate_image(image_path, pixel_size):
img = Image.open(image_path)
img = img.resize((img.width // pixel_size, img.height // pixel_size), Image.NEAREST)
return img
# Bild pixelieren und anzeigen
pixelated_img_1 = pixelate_image('IMG_1450_converted.png', 3)
plt.imshow(pixelated_img_1)
plt.axis('off')
plt.show()
plt.imshow(image_1)
plt.axis('off')
plt.show()
Das Bild wurde nun runterskaliert, optisch sieht man jedoch kaum einen Unterschied. Nun werde ich auch hier die Grösse der Pixel berechnen.
# Berechnung für image_1
pixelgroesse_image_1, breite_image_1, hoehe_image_1, pixelanzahl_image_1 = berechne_pixelgroesse(image_1, physische_flaeche)
# Berechnung für pixelated_1
pixelgroesse_img_1, breite_img_1, hoehe_img_1, pixelanzahl_img_1 = berechne_pixelgroesse(pixelated_img_1, physische_flaeche)
# Ergebnisse anzeigen
print(f"Bild: image_1")
print(f"Dimensionen: {breite_image_1}x{hoehe_image_1}")
print(f"Anzahl der Pixel: {pixelanzahl_image_1}")
print(f"Größe jedes Pixels: {pixelgroesse_image_1:.10f} Quadratmeter\n")
print(f"Bild: pixelated_image_1")
print(f"Dimensionen: {breite_img_1}x{hoehe_img_1}")
print(f"Anzahl der Pixel: {pixelanzahl_img_1}")
print(f"Größe jedes Pixels: {pixelgroesse_img_1:.10f} Quadratmeter\n")
# Vergleich der beiden Bilder
verhaeltnis = pixelgroesse_image_3 / pixelgroesse_img_3_down
print(f"Das Verhältnis der Pixelgrößen (Original / Verpixelt) ist: {verhaeltnis:.2f}")
Die Vergrösserung der Pixel ist im vergleich wieder die gleiche. Die Pixelanzahl wurde jedoch stark verringert.
Meine zwei Bilder wurden von der Auflösung verringert, wodurch die Speicherkapazität verringert wurde. Die zweite Methode hat jedoch besser funktioniert, da ich hier die Auflösung mehr verschlechtern konnte.
Experiment 2¶
WAS: Das zweite Problem ist die Klarheit des Bildes, die das Zählen und Erkennen von kleinen Objekten und Umrissen wie Enten erschwert.
WIE: Ich werde experimentieren, indem ich die Helligkeit der Bilder gezielt erhöhe oder reduziere, um die Sichtbarkeit von Enten und Flaggen zu verbessern. Verschiedene Helligkeitsstufen werden getestet, um die optimale Sichtbarkeit der Objekte zu erreichen.
WARUM: Durch die Anpassung der Helligkeit wird es einfacher, die relevanten Objekte in den Bildern zu erkennen und zu zählen, ohne andere Bilddetails zu verlieren. So kann ich all die Enten in meinem Bild erkennen und zählen.
(Der Text wurde mit ChatGPT verbessert)
Option 1:
Das Bild 2 wird mit dem Paket Pillow (Enhancer) aufgehellt. Dabei wird die Helligkeit des gesamten Bildes erhöht, indem die Helligkeitswerte proportional zu den bestehenden Pixelwerten angepasst werden.
from PIL import ImageEnhance
enhancer = ImageEnhance.Brightness(image_2)
# Helligkeit ändern
helleres_bild = enhancer.enhance(5) # Erhöht die Helligkeit
dunkleres_bild = enhancer.enhance(0.7) # verringert die Helligkeit
# Bild anzeigen
plt.imshow(helleres_bild)
plt.axis('off')
plt.show()
plt.imshow(dunkleres_bild)
plt.axis('off')
plt.show()
Leider sind beide Ergebnisse nicht sehr vielversprechend für meine Analyse. Wenn ich das Bild um 50% erhelle verschwinden langsam die Enten ganz vorne und ich weis leider immer noch nicht, ob im Hintergrund noch mehr Enten vorhanden sind. Ebenfalls beim verdunkeln, dort werden alle Enten undeutlicher.
Option 2:
Linear Histogram Equalization. Mit dieser Methode werden die Helligkeitswerte eines Bildes gleichmässig verteilt. Dadurch werden die dunklen Stellen weniger Dominant, was eine Erhöhung der Helligkeit bewirkt.
from PIL import ImageOps
# Histogramm-Equalization
equalized_image = ImageOps.equalize(image_2)
# Bild anzeigen
plt.imshow(equalized_image)
plt.axis('off')
plt.show()
image_2_grey = image_2.convert('L')
# Histogramm-Equalization
equalized_image_grey = ImageOps.equalize(image_2_grey)
# Bild anzeigen
plt.imshow(equalized_image_grey, cmap='gray')
plt.axis('off')
plt.show()
Bei dem farbigen Bild erkennt man optisch im Hintergrund schon ein wenig mehr, jedoch ist es für mich immer noch sehr schwer zu erkennen, ob sich im Schatten noch mehr Enten befinden. Ich werde als letzten Schritt in das Originale Bild hineinzoomen und dann die Helligkeit anpassen.
# Zoombereich
zoom_image = image_2.crop((1000, 1500, 2000, 2500))
equalized_zoom = ImageOps.equalize(zoom_image)
# Bild anzeigen
plt.imshow(equalized_zoom)
plt.axis('off')
plt.show()
Die Enten sind nun sehr deutlich sichtbar und man erkennt, dass sich im Hintergrund keine weiteren Enten mehr aufhalten.
Um meine Ergebnisse noch weiter zu analysieren, werde ich zu den jeweiligen Bildern noch ein Histogramplot erstellen, welches mir dei Verteilung der Graustufen zeigt.
image_2 = image_2.crop((1000, 1500, 2000, 2500))
helleres_bild = helleres_bild.crop((1000, 1500, 2000, 2500))
equalized_image_grey = equalized_image_grey.crop((1000, 1500, 2000, 2500))
image_2 = image_2.convert('L')
helleres_bild = helleres_bild.convert('L')
equalized_zoom = equalized_zoom.convert('L')
# Liste der Bilder
images = [
[image_2, 'original'],
[helleres_bild, 'Helles Bild'],
[equalized_image_grey, 'Linear Histogram\nEqualization'],
[equalized_zoom, 'Zoom\n& Equalization']
]
fig, axs = plt.subplots(nrows=2, ncols=len(images), figsize=(12, 8))
# Plot
for idx, img in enumerate(images):
axs[0][idx].imshow(img[0], cmap='gray')
axs[0][idx].axis('off')
axs[0][idx].set_title(img[1])
# Display the histogram
axs[1][idx].hist(np.array(img[0]).flatten(), bins=255, color='orange')
axs[1][idx].set_xlim(0, 255)
axs[1][idx].set_ylim(0, 40000)
axs[1][idx].set_title(img[1])
plt.tight_layout()
plt.show()
# Dieser Code wurde mit Hilfe des DeepDives Part 1 erstellt
Das Histogramm des gezoometen Bildes zeigt eine bessere Verteilung der Helligkeitswerte. Es gibt keine extremen Spitzen in einem bestimmten Bereich, was bedeutet, dass sowohl die dunklen als auch die hellen Bereiche des Bildes verbessert wurden.
Das Histogramm des Originalbilds zeigt eine starke Konzentration der Pixel in den dunklen Bereichen (niedrige Werte). Dies erklärt, warum das Bild so dunkel erscheint und man die Enten schlecht erkennt.
Das Histogramm des zweiten Bildes zeigt viele hohe Spitzen, was auf eine übermäßige Konzentration auf bestimmte Helligkeitsbereiche hinweist, da das Bild in allen Pixeln erhellt wurde.
Bei dem dritten Bild gibt es ebenfalls eine ungleichmäßige Verteilung, wobei man hier die dunkle Stelle schon besser erkennen kann.
Auswertung Experiment 1¶
Für mein erstes Experiment werde ich den SSIM (Structural Similarity Index) anwenden, um das Originalbild mit dem Bild mit schlechterer Auflösung zu vergleichen. Die Methode ist nützlich, da ich meine Bilder kleiner machten möchte, dabei aber keinen grossen Unterschied im Bild sehen möchte.
from skimage import io, color
from skimage.metrics import structural_similarity as ssim
from skimage.transform import resize
gray_image_3 = color.rgb2gray(image_3)
gray_image_3_down = color.rgb2gray(img_3_down)
# Resize gray_image_3_down to match gray_image_3 dimensions
gray_image_3_down_resized = resize(gray_image_3_down, gray_image_3.shape)
# Berechnen des SSIM-Werts
ssim_value, ssim_image = ssim(gray_image_3, gray_image_3_down_resized, full=True, data_range=gray_image_3.max() - gray_image_3.min())
# Ausgabe des SSIM-Werts
print(f'SSIM-Wert: {ssim_value}')
# Anzeigen der Bilder und des SSIM-Bildes
fig, axes = plt.subplots(1, 3, figsize=(10, 4))
ax = axes.ravel()
ax[0].imshow(gray_image_3, cmap='gray')
ax[0].set_title('Bild 1')
ax[0].axis('off')
ax[1].imshow(gray_image_3_down, cmap='gray')
ax[1].set_title('Bild 2')
ax[1].axis('off')
ax[2].imshow(ssim_image, cmap='gray')
ax[2].set_title('SSIM-Bild')
ax[2].axis('off')
plt.tight_layout()
plt.show()
# Dieser Code wurde mit Hilfe von Copilot geschrieben
Der SSIM-Wert ist gleich 0.91. Ein Wert von 1 bedeutet, dass die Bilder sich perfekt ähnlich sehen.
Das SSIM-Bild ist eine Pixel-für-Pixel-Darstellung der strukturellen Ähnlichkeit zwischen den beiden Bildern. Helle Bereiche im SSIM-Bild zeigen Regionen, in denen die beiden Bilder sehr ähnlich sind. Das bedeutet, dass diese Bereiche in beiden Bildern praktisch die gleiche Struktur, Helligkeit und Kontrasteigenschaften haben.
Dunkle Bereiche weisen darauf hin, dass es in diesen Bereichen Unterschiede zwischen den beiden Bildern gibt. Je dunkler der Bereich, desto größer die Unterschiede in Struktur und Kontrast zwischen den beiden Bildern.
Man erkennt also, dass die Bilder sich noch sehr ähnlich sehen in Bezug auf die Struktur, Helligkeit und Kontrasteigenschaften.
Für das zweite Bild werde ich die Entropie der beiden Bilder vergleichen. Die Entropie misst die Informationsmenge im Bild. Da ich im Bild nur die Auflösung verändert habe gibt es dementsprechend auch keine starken Veränderung, weswegen ich testen möchte, ob sich die Informationsmenge verschlechtert hat.
from scipy.stats import entropy
# Konvertieren des Bildes in Graustufen
gray_image = color.rgb2gray(image_1)
gray_image_pix = color.rgb2gray(pixelated_img_1)
# Berechnen des Histogramms
histogram, _ = np.histogram(gray_image, bins=256, range=(0, 1), density=True)
histogram_pix, _ = np.histogram(gray_image_pix, bins=256, range=(0, 1), density=True)
# Berechnen der Entropie
image_entropy = entropy(histogram)
image_entropy_pix = entropy(histogram_pix)
# Ausgabe
print(f'Entropie des Bildes: {image_entropy}')
print(f'Entropie des schlechteren Bildes: {image_entropy_pix}')
Eine hohe Entropie bedeutet, dass das Bild mehr Informationen enthält. Das erste Bild hat eine Auflösung von 4K, während das zweite Bild eine AUflösung von 1344x1008. Dennoch haben beide Bilder eine sehr ähnliche Entropie von 4.92, was bedeutet, dass so gut wie keine Informationen im Bild verloren gegenagen sind.
Auswertung Experiment 2¶
Für mein zweites Experiment werde ich die Canny Edge Detection anwenden. Dies ist ein ALgorithmus, der die Kanten in einem Bild misst. Dies gibt mir ein Mass dafür, wie gut die Kanten nach der Kontrastanpassung meines Bildes erkannt werden.
from skimage import feature
image_2_array = np.array(image_2.convert('L'))
zoom_image_array = np.array(zoom_image.convert('L'))
# Canny Edge Detection
edges_image_2 = feature.canny(image_2_array)
edges_zoom = feature.canny(zoom_image_array)
# Bild anzeigen
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
ax = axes.ravel()
ax[0].imshow(image_2_array, cmap='gray')
ax[0].set_title('Original Bild')
ax[0].axis('off')
ax[1].imshow(edges_image_2, cmap='gray')
ax[1].set_title('Canny Edges - Original Bild')
ax[1].axis('off')
ax[2].imshow(edges_zoom, cmap='gray')
ax[2].set_title('Canny Edges - Verarbeitetes Bild')
ax[2].axis('off')
plt.tight_layout()
plt.show()
Durch die Canny Edge Methode werden die Kanten sichtbar. Beide Bilder ähneln sich sehr beim erkennen der Kanten. Leider wird aber nur eine Ente deutlich sichtbar, die anderen Enten kann man nicht erkennen. Das Problem liegt darin, dass die Enten auf dem Wasser schwimmen und es dort sehr viele Details gibt.
Vergleich der Histogramme¶
Im folgenden schauen wir uns die Verteilung der Helligkeitswerte in den Bildern an, im vergleich zu den bearbeiteten Bildern. Die Histogramme der schwarz/weissen Pixel ist für mich interessanter, also die RGB-Farben, da ich mich vor allem auf die Kontraste im Bild und auf die Helligkeitsverteilung fokussiert habe.
image_3 = image_3.convert('L')
gray_image_3_down = img_3_down.convert('L')
# Liste der Bilder
images = [
[image_3, 'original'],
[gray_image_3_down, 'Pixeliertes Bild']
]
fig, axs = plt.subplots(nrows=2, ncols=len(images), figsize=(12, 8))
# Plot
for idx, img in enumerate(images):
axs[0][idx].imshow(img[0], cmap='gray')
axs[0][idx].axis('off')
axs[0][idx].set_title(img[1])
# Display the histogram
axs[1][idx].hist(np.array(img[0]).flatten(), bins=255, color='orange')
axs[1][idx].set_xlim(0, 255)
axs[1][idx].set_ylim(0, 160000)
axs[1][idx].set_title(img[1])
plt.tight_layout()
plt.show()
Originalbild:
Das Histogramm des Originalbildes zeigt eine breite Verteilung der Helligkeitswerte, die zwischen etwa 0 (schwarz) und 250 (fast weiß) reicht. Die Kurve hat einen Höhepunkt bei den mittleren Graustufen. Der Verlauf des Histogramms zeigt, dass das Originalbild ein ausgewogenes Verhältnis zwischen dunklen, mittleren und hellen Bereichen hat.
Pixeliertes Bild:
Da das rechte Bild durch eine Halbierung der Pixelanzahl entstanden ist (von 4K auf 2K), bedeutet das, dass das Bild weniger Pixel enthält. Dies führt dazu, dass zwar Details verloren gehen, die allgemeine Struktur und Helligkeitsverteilung jedoch weitgehend erhalten bleiben. Der Hauptunterschied zu einer starken Pixelierung besteht darin, dass trotz der Reduktion der Auflösung die grundlegende Verteilung der Helligkeitswerte erhalten bleibt, aber weniger feine Details dargestellt werden. Dies kann das Bild weniger scharf erscheinen lassen.
image_1 = image_1.convert('L')
pixelated_image_1 = pixelated_img_1.convert('L')
# Liste der Bilder
images = [
[image_1, 'original'],
[pixelated_image_1, 'Pixeliertes Bild']
]
fig, axs = plt.subplots(nrows=2, ncols=len(images), figsize=(12, 8))
# Plot
for idx, img in enumerate(images):
axs[0][idx].imshow(img[0], cmap='gray')
axs[0][idx].axis('off')
axs[0][idx].set_title(img[1])
# Display the histogram
axs[1][idx].hist(np.array(img[0]).flatten(), bins=255, color='orange')
axs[1][idx].set_xlim(0, 255)
axs[1][idx].set_ylim(0, 160000)
axs[1][idx].set_title(img[1])
plt.tight_layout()
plt.show()
Originalbild:
Das Histogramm des Originalbildes zeigt eine komplexe Verteilung der Helligkeitswerte. Es gibt mehrere Spitzen: Eine erste deutliche Konzentration im dunkleren Bereich (0 bis 50), was auf die dunklen Bereiche im Bild (z. B. Bäume und Fahrzeuge) hinweist. Eine sehr deutliche Spitze um den Bereich von 100, was wahrscheinlich den grauen Himmel und die mittelhellen Elemente darstellt. Der Rest des Histogramms verteilt sich auf den mittleren und helleren Bereich, was die Vielfalt der Helligkeiten im Originalbild widerspiegelt.
pixelreduziertes Bild:
Das Histogramm des pixelreduzierten Bildes zeigt eine deutlich stärkere Kompression der Helligkeitswerte, aber wir können trotzdem eine ähnliche Struktur wie im Originalbild erkennen (wie zuvor bei Bild 3). Der erste Höhepunkt liegt wieder im Bereich 0 bis 50, was auf die dunklen Bereiche im Bild (wie Bäume und Fahrzeuge) hinweist. Die markante Spitze bei etwa 100 bleibt bestehen, jedoch ist diese im reduzierten Bild weniger ausgeprägt, was auf die Verringerung der Details und der Auflösung hindeutet. Der gesamte Bereich nach 150 ist nahezu leer, was darauf hinweist, dass im pixelreduzierten Bild weniger Helligkeitskontrast und feine Details erfasst wurden.
Schlusswertung¶
In meinem Experiment 1, das sich mit der Reduzierung der Bildauflösung befasste, konnte ich feststellen, dass die Entropie der Bilder nahezu identisch blieb, was darauf hindeutet, dass kaum Informationen verloren gingen. Dies wurde auch bei dem Vergleich der Histogramme deutlich, denn die Kurver der Helligkeitsverteilung ist nahezu indetisch, die Anzahl Pixel ist einfach niedriger (und somit ist das Histogramm flacher). Bei der Verringerung der Pixelgrösse stieg die Grösse der Pixel um das Vierfache. Trotz dieser erheblichen Reduzierung blieb die Entropie nahezu gleich, was darauf hinweist, dass nur wenige Informationen verloren gingen. Das Bild zeigte visuell minimale Unterschiede, was die Annahme bestätigt, dass bei Bildern ohne feine Details, wie sie in diesem Experiment verwendet wurden, die Reduktion der Pixelanzahl und damit die Verrgrösserung der Pixel kaum Einfluss auf die wahrgenommene Qualität hat. Dies ist besonders relevant für Anwendungen, bei denen Speicherplatz und Bandbreite optimiert werden müssen.
In Experiment 2 habe ich die Helligkeit angepasst, um zu überprüfen, ob sich im dunklen Hintergrund weitere Enten verbergen. Optisch war das Ergebnis zufriedenstellend: Die Kontraste und die Helligkeit konnten so verändert werden, dass deutlich wurde, dass keine weiteren Enten im Hintergrund vorhanden sind. Im Histogramm zeigt sich die Veränderung der Helligkeit auch, denn die verschiedenen Helligkeitswerte sind stärker verteilt (die dunklen Stufen wurden weniger, dafür gibt es mehr Helligkeitswerte). Allerdings reichte diese Anpassung nicht aus, um verschiedene Algorithmen bei der Objekterkennung zu unterstützen. Aufgrund der reflektierenden Oberflächen, insbesondere des Wassers, waren die Algorithmen nicht in der Lage, die Enten als separate Objekte zu identifizieren. Dies zeigt, dass einfache Helligkeitsanpassungen zwar visuell hilfreich sein können, aber nicht ausreichen, um die Leistung von Erkennungsalgorithmen in solchen komplexen Szenarien zu verbessern.
(Der Text wurde mit ChatGPT verbessert)
Die ersten Tage meiner Reise durch Frankreich waren wirklich sehr schön. Von den Sonnenuntergängen in Paris, zu einer meiner liebliengsbeschäftigung in Le Mans (Tiere beobachten und analysieren) bis hin zum Stand in die Normandie. Durch die Bearbeitung meiner Bilder kann ich mein Reisetagebuch nun in ein digitales Fotobuch laden und in mein Wohnzimmer stellen.